<?php
/**
 * Author : 葛洒洒
 * Date: 2018/7/30
 * Time: 16:31
 *
 * 感谢 @葛洒洒 提供PHP接入代码
 */

class Alichat
{
    /**
     * 租户id，由云客服提供
     * 开通租户后, 可以在聊天窗管理URL中TntInstId参数中看到
     * @var string
     */
    private $tntInstId  = 'XXXXXX';

    /**
     * 聊天窗编码，由云客服提供
     * 开通租户后, 在聊天窗管理中聊天窗编码看到
     * @var string
     */
    private $scene     = 'SCE0000XXXX';

    /**
     * 摘要计算(hmac_sha1)所需密钥，由云客服提供
     * 联系售后|提工单 获取
     * @var string
     */
    private $key       = 'XXXXXXXXXXXXXXXXXXXXX';

    /**
     * 消息内容
     * @var string
     */
    private $data;


    /**
     * 请求路径 requestURL
     * @var string
     */
    private $requestURL;

    /**
     * 统一发送消息接口
     * 该接口只支持POST请求
     */
    private $forwardMessageURL  = 'https://cschat-ccs.aliyun.com/openapi/forwardMessage';

    /**
     * 上传文件接口调用
     */
    private $uploadFile        = 'https://cschat-ccs.aliyun.com/openapi/uploadFile';

    /**
     * 文件获取接口调用
     */
    private $fetchFile         = 'https://cschat-ccs.aliyun.com/openapi/fetchFile';

    /**
     * 本次调用的时间戳
     * @var integer
     */
    private $curTime = 0;

    /**
     * 构造函数
     * Alichat constructor.
     */
    public  function __construct()
    {
        $this->curTime = $this->getMillisecond();    //获取当前微秒,保证唯一值。
    }

    /**
     * 基础类核心请求方法
     * @param array $arr 数组
     * @return bool|mixed 接口返回数据
     */
    public function core($arr=[]){
        $arr['timestamp'] =  $this->curTime;
        $this->data = json_encode($arr);
        $url = $this->getUrl($this->data);
        $exec = $this->post($url,$this->data);
        return $exec;
    }

    /**
     * 文件类核心请求方法
     * @param array $arr 数组
     * @return bool|mixed 接口返回数据
     */
    public function fileCore($arr=[],$file=''){
        $this->data = $arr;
        $url = $this->getUrl($file);
        //获取图片，直接请求url取结果
        if ($arr['fileKey']){
            $url = $url.'&fileKey='.$arr['fileKey'];
            return file_get_contents($url);
        }
        $exec = $this->post($url,$this->data,true);
        return $exec;
    }

    /**
     * 拼接url
     * @param string $secret
     * @return string
     */
    public function getUrl($secret){
        $params =  [
            "tntInstId" => $this->tntInstId,
            "timestamp" => $this->curTime,
            'src'=>'outerservice',
            'digest'=>$this->hmac_sha1($secret),
            'scene'=>$this->scene,
        ];
        $str = '';
        foreach ($params as $k => $val) {
            $str .= "{$k}={$val}&"; //拼接成 key1=value1&key2=value2&...&keyN=valueN& 的形式
        }
        $url = $this->requestURL.'?'.$str;
        $url = rtrim($url,'&');
        return $url;
    }


    /**
     * 上传文件
     * @param $data
     * @return bool|mixed
     */
    public function uploadFile($data,$file)
    {
        if (empty($data) || !is_array($data)) return 'must be array';
        $this->requestURL = $this->uploadFile;
        return $this->fileCore($data,$file);
    }

    /**
     * 获取文件
     * @param $data
     * @return bool|mixed
     */
    public function fetchFile($data,$fielkey)
    {
        if (empty($data) || !is_array($data)) return 'must be array';
        $this->requestURL = $this->fetchFile;
        return $this->fileCore($data,$fielkey);
    }


    /**
     * 发送消息
     * @param $data
     * @return bool|mixed
     */
    public function forwardMessage($data)
    {
        if (empty($data) || !is_array($data)) return 'must be array';
        $this->requestURL = $this->forwardMessageURL;
        return $this->core($data);
    }

    /**
     * 转byte数组
     * @param $string
     * @return array
     */
    public static function getBytes($string){
        $bytes = array();
        for($i = 0; $i < strlen($string); $i++){
            $bytes[] = ord($string[$i]);
        }
        return $bytes;
    }


    /**
     * 加密算法
     * @return string
     */
    function hmac_sha1($file) {
        $str = $file.$this->curTime;
        $key = $this->key;
        $signature = "";
        if (function_exists('hash_hmac')) {
            $signature = bin2hex(hash_hmac("sha1", $str, $key, true));
        } else {
            $blocksize = 64;
            $hashfunc = 'sha1';
            if (strlen($key) > $blocksize) {
                $key = pack('H*', $hashfunc($key));
            }
            $key = str_pad($key, $blocksize, chr(0x00));
            $ipad = str_repeat(chr(0x36), $blocksize);
            $opad = str_repeat(chr(0x5c), $blocksize);
            $hmac = pack(
                'H*', $hashfunc(
                    ($key ^ $opad) . pack(
                        'H*', $hashfunc(
                            ($key ^ $ipad) . $str
                        )
                    )
                )
            );
            $signature = bin2hex($hmac);
        }
        return $signature;
    }

    /**
     * 转字符串为二进制
     * @param $str
     * @return string
     */
    function StrToBin($str){
        $str = $this->getMillisecond();
        //1.列出每个字符
        $arr = preg_split('/(?<!^)(?!$)/u', $str);
        //2.unpack字符
        foreach($arr as &$v){
            $temp = unpack('H*', $v);
            $v = base_convert($temp[1], 16, 2);
            unset($temp);
        }
        return join(' ',$arr);
    }


    /**
     * 获取当前毫秒
     * @return float
     */
    function getMillisecond() {
        list($s1, $s2) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
    }


    /**
     * post请求
     * @param $url
     * @param string $data
     * @param string $form
     * @return mixed
     */
    function post($url,$data = '',$form=''){
        $ch = curl_init ();
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ( $ch, CURLOPT_POSTFIELDS,$data);
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER,false); //禁止 cURL 验证对等证书
        //模拟表单提交
        if ($form){
            $header=array(
                "Content-Type: multipart/form-data",
            );
            curl_setopt( $ch,CURLOPT_HTTPHEADER,$header);
        }else{
            //模拟提交json数据
            $header=array(
                "Accept: application/json",
                "Content-Type: application/json;charset=utf-8",
            );
            curl_setopt( $ch,CURLOPT_HTTPHEADER,$header);
        }
        $return = curl_exec ( $ch );
        curl_close ($ch);
        return $return;
    }


}